//////////////////////////////////////////////
// JpgBitWriter.h
//
//////////////////////////////////////////////

/// Defines / Macros -------------------------

#pragma once

/// Class ------------------------------------

namespace nkImages::jpg
{
	// Aimed at scan data, with all the specs of it implemented
	// For instance, checking and stuffing FF[00] bytes
	class JpgBitWriter final
	{
		public :

			// Attributes
			// Stream & state holding
			unsigned char* _out ;
			unsigned int _bitCounter ;
			unsigned int _byteCounter ;

		public :

			// Functions
			// Constructor
			JpgBitWriter (unsigned char* out)
			:	_out (out),
				_bitCounter (0u),
				_byteCounter (0u)
			{
				// Nothing todo
			}

			// Bit writing
			void writeBits (unsigned int data, unsigned int bitCount)
			{
				// Write bits while we need, modulo 8
				// Mask for getting good bits while writing (should always have bits set, as int is longer than 16 bits)
				unsigned int currentMask = 0xFFFFFFFF << bitCount ;

				while (bitCount)
				{
					// Check what we can write
					unsigned int bitWriteCount = std::min(bitCount, 8 - _bitCounter) ;

					// Write info
					unsigned int toWrite = (data & ~currentMask) >> (bitCount - bitWriteCount) ;
					_out[_byteCounter] = (_out[_byteCounter] << (bitWriteCount)) + (unsigned char)(toWrite & 0b11111111) ;

					// Forward
					// Byte stuff if needed
					if (_out[_byteCounter] == 255)
					{
						_out[_byteCounter + 1] = 0 ;
						_byteCounter++ ;
					}

					// Forward with memory
					bitCount -= bitWriteCount ;
					_bitCounter += bitWriteCount ;
					_byteCounter += _bitCounter / 8u ;
					_bitCounter %= 8u ;
					currentMask >>= bitWriteCount ;
				}
			}

			// Pad once stream should be finalized
			void finalizeLastByte ()
			{
				if (_bitCounter)
					_out[_byteCounter] <<= 8 - _bitCounter ;
			}
	} ;
}